﻿// -----------------------------------------------------------------------
// <copyright file="WebAbstractions.cs" company="CompDJ">
//     Copyright (c) CompDJ. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace CompDJ.Web.Abstractions.UnitTests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using FakeItEasy;

    /// <summary>Web abstractions class.</summary>
    public class WebAbstractions
    {        
        /// <summary>Prevents a default instance of the WebAbstractions class from being created.</summary>
        private WebAbstractions()
        {
        }

        /// <summary>Gets a new instance of the WebAbstractions class.</summary>
        public static WebAbstractions Factory
        {
            get
            {
                return new WebAbstractions();
            }
        }

        /// <summary>Initializes the mock object{T}</summary>
        /// <typeparam name="T">Type of object to mock</typeparam>
        /// <param name="initRoutine">Routine to initialize the mock</param>
        /// <returns>Returns the mock instance {T}</returns>
        public T InitializeMock<T>(Action<T> initRoutine)
        {
            var obj = A.Fake<T>();

            if (initRoutine != null)
            {
                initRoutine.Invoke(obj);
            }

            return obj;
        }

        /// <summary>Initializes the mock object{T}</summary>
        /// <typeparam name="T">Type of object to mock</typeparam>
        /// <param name="initRoutine">Routine to initialize the mock</param>
        /// <param name="parameters">Parameters for constructor</param>
        /// <returns>Returns the mock instance {T}</returns>
        public T InitializeMock<T>(Action<T> initRoutine, IEnumerable<object> parameters)
        {
            var obj = A.Fake<T>(x => x.WithArgumentsForConstructor(parameters));

            if (initRoutine != null)
            {
                initRoutine.Invoke(obj);
            }

            return obj;
        }

        /// <summary>Initializes the mock objects.</summary>
        /// <param name="formsAuthenticationRoutine">Action to initialize the mock for FormsAuthenticationFactory</param>
        /// <param name="membershipRoutine">Action to initialize the mock for MembershipFactory</param>
        /// <param name="configurationManagerRoutine">Action to initialize the mock for ConfigurationManagerFactory</param>
        /// <param name="httpContextBaseRoutine">Action to initialize the mock for HttpContextFactory</param>
        public void InitializeMock(
            Action<IFormsAuthentication> formsAuthenticationRoutine,
            Action<IMembership> membershipRoutine,
            Action<IConfigurationManager> configurationManagerRoutine,
            Action<HttpContextBase> httpContextBaseRoutine)
        {
            IFormsAuthentication formsAuthentication = this.InitializeMock<IFormsAuthentication>(formsAuthenticationRoutine);
            IMembership membership = this.InitializeMock<IMembership>(membershipRoutine);
            IConfigurationManager configurationManager = this.InitializeMock<IConfigurationManager>(configurationManagerRoutine);

            HttpContextBase httpContextBase = this.InitializeMock<HttpContextBase>(h =>
            {
                A.CallTo(() => h.Request).Returns(this.InitializeMock<HttpRequestBase>(null));
                A.CallTo(() => h.Response).Returns(this.InitializeMock<HttpResponseBase>(null));
                A.CallTo(() => h.Session).Returns(this.InitializeMock<HttpSessionStateBase>(null));
                A.CallTo(() => h.Server).Returns(this.InitializeMock<HttpServerUtilityBase>(null));
                A.CallTo(() => h.User).Returns(this.InitializeMock<System.Security.Principal.IPrincipal>(null));

                if (httpContextBaseRoutine != null)
                {
                    httpContextBaseRoutine.Invoke(h);
                }
            });

            FormsAuthenticationFactory.SetContext(formsAuthentication);
            MembershipFactory.SetContext(membership);
            ConfigurationManagerFactory.SetContext(configurationManager);
            HttpContextFactory.SetContext(httpContextBase);
        }

        /// <summary>Resets all factories to use default values.</summary>
        public void ResetAllFactories()
        {
            MembershipFactory.SetContext(null);
            HttpContextFactory.SetContext(null);
            ConfigurationManagerFactory.SetContext(null);
            FormsAuthenticationFactory.SetContext(null);

            MembershipFactory.SetCreationFunction(null);
            HttpContextFactory.SetCreationFunction(null);
            ConfigurationManagerFactory.SetCreationFunction(null);
            FormsAuthenticationFactory.SetCreationFunction(null);
        }
    }
}
